//---------------------------------------------------------------------
// File: XmlValidateWithAltovaStep.cs
// 
// Summary: Provides XML Validation using Altova
//
// Copyright (c) Hammersmith & Fulham Bridge Partnership. All rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//---------------------------------------------------------------------

using System;
using System.Xml;
using Microsoft.Services.BizTalkApplicationFramework.BizUnit;
using Altova.AltovaXML;

namespace BizUnit.Extensions.Altova
{
    /// <summary>
    /// A wrapper class over the AltovaXml library. This is required because the standard 
    /// Xml validation fails when the target has multiple schemas imported with relative locations
    /// specified. The Altova wrapper appears to work fine with these scenarios.
    /// This can be used in conjunction with the dotnetobjectinvoker step to validate a file. 
    /// </summary>
    /// <remarks>
    /// The following shows an example of the Xml representation of this test step.
    /// 
    /// <code escaped="true">
    ///	<TestStep assemblyPath="BizUnit.Extensions.Altova.dll" typeName="BizUnit.Extensions.XmlValidateWithAltovaStep">
    ///	<BaseString>Update table set fld = '{0}' where fld1 = '{1}'</BaseString>
    ///	<Delimiter>|</Delimiter>
    ///	<NumParams>2</NumParams>
    ///	<ParamString>Smith|10192929239</ParamString>
    ///	<ContextKey>OutputString</ContextKey>
    ///	</TestStep>
    ///	</code>
    ///	
    ///	<list type="table">
    ///		<listheader>
    ///			<term>Tag</term>
    ///			<description>Description</description>
    ///		</listheader>
    ///		<item>
    ///			<term>InputFileName</term>
    ///			<description>full path of the xml file to validate</description>
    ///		</item>
    ///		<item>
    ///			<term>SchemaFileName</term>
    ///			<description>full path of the schema file to validate the input file against</description>
    ///		</item>
    ///	</list>
    ///	</remarks>
	public class XmlValidateWithAltovaStep : ITestStep
	{
       
		/// <summary>
		/// Execute the XmlValidateWithAltova step 
		/// </summary>
		/// <param name='testConfig'>The Xml fragment containing the configuration for this test step</param>
		/// <param name='context'>The context for the test, this holds state that is passed beteen tests</param>
		public void Execute(XmlNode testConfig, Context context)
		{
			string InputFileName = context.ReadConfigAsString( testConfig, "InputFileName" );
            string SchemaFileName = context.ReadConfigAsString(testConfig, "SchemaFileName");
		    string ValidationAssertion = context.ReadConfigAsString(testConfig, "ValidationAssertion", true);

            string validationMsg;
            bool bValidationResult;
		    bool bExpectedResult;
            if ((ValidationAssertion == null) || ValidationAssertion.ToUpper().Equals("TRUE"))
                bExpectedResult = true;
            else
                bExpectedResult = false;

			// Load XML document from input file
			try
			{
                ApplicationClass appXML = new ApplicationClass();

                XMLValidator XMLValidator = appXML.XMLValidator;
                XMLValidator.InputXMLFileName = InputFileName;
                XMLValidator.SchemaFileName = SchemaFileName;
                bValidationResult = XMLValidator.IsValidWithExternalSchemaOrDTD();
                validationMsg = XMLValidator.LastErrorMessage;

                if(bValidationResult==bExpectedResult)
                {
                    context.LogInfo("Validation succeeded");
                }
                else
                {
                    string Message =
                        String.Format("Validation Assertion failed. Expected {0} but was {1}", bExpectedResult,
                                      bValidationResult);
                    Exception ex = new Exception(Message);
                    context.LogError(Message);
                    throw ex;
                }

            }
			//catch any exceptions from the try block
            catch (Exception ex)
			{
				context.LogException(ex);
			}

		}

    }
}
